// =================实现简单的虚拟DOM生成和真实DOM渲染=========================
/**
 * 流程：
 * 1. jsx语法下的DOM结构
 * 2. babel调用createElement将jsx结构转化为虚拟DOM
 * 3. 调用render方法将虚拟DOM转化为真实DOM并挂载
 */

// 虚拟DOM类
class VDom {
    // 构造虚拟DOM对象
    constructor(tag, attributes, children) {
        this.tag = tag;
        this.attributes = attributes;
        this.children = children
    }
    // 实例方法：虚拟DOM --> 真实DOM。返回生成的真实DOM
    V2R() {
        // 外层转为真实DOM
        let rtag = document.createElement(this.tag);
        // 为其挂载行内属性
        Object.keys(this.attributes).forEach(key => {
            switch (key) {
                case 'className':
                    rtag.setAttribute('class', this.attributes[key]);
                    break;
                case 'htmlFor':
                    rtag.setAttribute('for', this.attributes[key]);
                    break;
                case 'style':
                    let str = ``;
                    Object.keys(this.attributes[key]).forEach(item => {
                        str += `${item}:${this.attributes[key][item]};`
                    })
                    rtag.setAttribute('style', str)
                    break;
                default:
                    rtag.setAttribute(key, this.attributes[key])
                    break;
            }

        });
        // 递归添加子节点
        this.children.forEach(child => {
            child instanceof VDom ?
                // child是虚拟DOM节点，递归它
                rtag.appendChild(child.V2R()) :
                // child是文本节点，document创建文本节点
                rtag.appendChild(document.createTextNode(child))
        });
        return rtag;
    };
}


class my_react {
    // createElement方法返回虚拟DOM节点
    static createElement(tagName, attributes, ...children) {
        return new VDom(tagName, attributes, children)
    }
}

class my_reactDOM {
    static render(virtualDom, realDom) {
        // 调用虚拟DOM的转换方法
        let ele = virtualDom.V2R()
        realDom.appendChild(ele)
    }
}

















// 如下jsx字符串解析时会相应进入createElement的各个参数位置
let
    eleStr =
    `
    <div className="box" id: "myid" htmlFor: '001'>
        outerContent
        <div>
            innerContent
            <i style="{color: 'red',margin: '50px'}">icon</i>
        </div> 
    </div>
`;

// 调用createElement函数应传递的参数（参数的生成来自eleStr的解析），生成虚拟DOM
let vdom = my_react.createElement(
    // 最外标签名
    'div',
    // 行内属性
    {
        className: 'box',
        id: "myid",
        htmlFor: '001'
    },
    // 插槽中的文本节点 
    'outerContent',
    // 插槽中的dom结构节点
    my_react.createElement(
        'div', {},
        'innerContent',
        my_react.createElement(
            'i', {
                style: {
                    color: 'red',
                    margin: '50px'
                }
            },
            'icon'
        )
    )
)



// 渲染虚拟DOM，调用render函数将虚拟DOM转化为真实DOM并改在到root根标签中
my_reactDOM.render(vdom, document.getElementById('root'))